package org.darcy.service.org.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.darcy.dao.org.DepartmentMapper;
import org.darcy.entity.org.Company;
import org.darcy.entity.org.Department;
import org.darcy.entity.org.Staff;
import org.darcy.entity.privilege.SysUser;
import org.darcy.framework.constant.SysConstant;
import org.darcy.framework.generic.GenericServiceImpl;
import org.darcy.framework.model.PageData;
import org.darcy.framework.model.PageParam;
import org.darcy.service.org.CompanyService;
import org.darcy.service.org.OrgDepartmentService;
import org.darcy.service.org.StaffService;
import org.darcy.utils.common.ReturnCode;
import org.darcy.utils.vo.ReturnVo;
import org.darcy.vo.org.OrgTreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class DepartmentServiceImpl extends GenericServiceImpl<Department> implements OrgDepartmentService {

	@Autowired
	private CompanyService companyService;

	@Autowired
	private StaffService StaffService;

	@Autowired
	private DepartmentMapper mapper;

	@Override
	public PageData<Department> page(PageParam<Department> param) {
		IPage<Department> queryPage = new Page<Department>(param.getQuery().getPageNum(),
				param.getQuery().getPageSize());
		IPage<Department> data = mapper.getPage(queryPage, param.getEntity());
		PageData<Department> pageData = new PageData<Department>(data, param);
		return pageData;
	}

	@Override
	public ReturnVo<List> importDepartment(List<Department> departments, SysUser loginUser) {
		ReturnVo<List> returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "OK");
		if (CollectionUtils.isNotEmpty(departments)) {
			List<String> codes = new ArrayList<>();
			departments.forEach(department -> {
				if (StringUtils.isNotBlank(department.getCode())) {
					codes.add(department.getCode());
				}
			});
			LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
			departmentLambdaQueryWrapper.in(Department::getCode, codes);
			List<Department> oldDbDepartments = this.getList(departmentLambdaQueryWrapper);
			Map<String, Department> oldDbDepartmentMap = oldDbDepartments.stream()
					.collect(Collectors.toMap(Department::getCode, department -> department));
			List<Department> newDepartments = new ArrayList<>();
			List<Department> oldDepartments = new ArrayList<>();
			departments.forEach(department -> {
				String code = department.getCode();
				if (!oldDbDepartmentMap.containsKey(code)) {
					newDepartments.add(department);
				} else {
					oldDepartments.add(department);
				}
			});
			Map<String, Department> oldDepartmentMap = oldDepartments.stream()
					.collect(Collectors.toMap(Department::getCode, department -> department));
			if (CollectionUtils.isNotEmpty(oldDbDepartments)) {
				oldDbDepartments.forEach(department -> {
					Department newDepartment = oldDepartmentMap.get(department.getCode());
					convert(department, newDepartment);
				});
			}
			List<Department> totalDepartments = new ArrayList<>();
			totalDepartments.addAll(newDepartments);
			totalDepartments.addAll(oldDbDepartments);
			Map<String, Department> saveOrUpdateBatchMap = totalDepartments.stream()
					.collect(Collectors.toMap(Department::getCode, department -> department));
			List<Department> errorDepartments = new ArrayList<>();
			List<Department> saveOrUpdateBatch = new ArrayList<>();
			totalDepartments.forEach(department -> {
				if (StringUtils.isNotBlank(department.getPcode())) {
					department.setPid(saveOrUpdateBatchMap.get(department.getPcode()).getId());
				}
				Company company = companyService.getCompanyByCode(department.getCompanyCode());
				if (company != null) {
					department.setCompanyId(company.getId());
					saveOrUpdateBatch.add(department);
				} else {
					// 返回错误信息
					errorDepartments.add(department);
				}
			});
			this.updateBatch(saveOrUpdateBatch);
			if (CollectionUtils.isNotEmpty(errorDepartments)) {
				returnVo = new ReturnVo<>(ReturnCode.FAIL, "公司查询不到，请确认");
				returnVo.setData(errorDepartments);
			}
		}
		return returnVo;
	}

	void convert(Department oldDepartment, Department newDepartment) {
		oldDepartment.setName(newDepartment.getName());
		oldDepartment.setLeaderCode(newDepartment.getLeaderCode());
		oldDepartment.setNote(newDepartment.getNote());
		oldDepartment.setOrderNo(newDepartment.getOrderNo());
	}

	public void getAllDepartmentIds(Integer id, List<Integer> ids) {
		if (ids == null) {
			ids = new ArrayList<>();
		}
		ids.add(id);
		LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
		departmentLambdaQueryWrapper.eq(Department::getPid, id).eq(Department::getDelFlag, SysConstant.DEL_FLAG_1);
		long count = this.count(departmentLambdaQueryWrapper);
		if (count > 0) {
			List<Department> companyList = this.getList(departmentLambdaQueryWrapper);
			List<Integer> finalIds = ids;
			companyList.forEach(company -> this.getAllDepartmentIds(company.getId(), finalIds));
		} else {
			return;
		}
	}

	@Override
	public void saveOrUpdate(Department department, SysUser loginUser) {
		if (department.getId() != null) {
			this.update(department);
		} else {
			this.insert(department);
		}
	}

	@Override
	public ReturnVo<String> deleteByIds(List<String> ids) {
		ReturnVo<String> returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "OK");
		LambdaQueryWrapper<Staff> personalLambdaQueryWrapper = new LambdaQueryWrapper<>();
		personalLambdaQueryWrapper.in(Staff::getDeptId, ids).eq(Staff::getDelFlag, SysConstant.DEL_FLAG_1);
		long count = StaffService.count(personalLambdaQueryWrapper);
		if (count > 0) {
			returnVo = new ReturnVo<>(ReturnCode.FAIL, "请先移除部门相关人员!");
		} else {
			LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
			departmentLambdaQueryWrapper.eq(Department::getDelFlag, SysConstant.DEL_FLAG_1).eq(Department::getPid,
					ids.get(0));
			long departmentCount = this.count(departmentLambdaQueryWrapper);
			if (departmentCount > 0) {
				returnVo = new ReturnVo<>(ReturnCode.FAIL, "该部门还存在子部门，请确认!");
			} else {
				LambdaQueryWrapper<Department> departmentLambdaUpdateWrapper = new LambdaQueryWrapper<>();
				departmentLambdaUpdateWrapper.eq(Department::getDelFlag, SysConstant.DEL_FLAG_1).in(Department::getId,
						ids);
				this.delete(departmentLambdaUpdateWrapper);
			}
		}
		return returnVo;
	}

	@Override
	public List<Department> getAll(Department department) {
		return mapper.getDepartments(department);
	}

	@Override
	public List<OrgTreeVo> getDepartmentTree(Integer companyId, String deptName) {
		List<OrgTreeVo> orgTreeVos = new ArrayList<>();
		LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
		departmentLambdaQueryWrapper.eq(Department::getDelFlag, 1);
		if (companyId != null) {
			departmentLambdaQueryWrapper.eq(Department::getCompanyId, companyId);
		}
		if (StringUtils.isNotBlank(deptName)) {
			departmentLambdaQueryWrapper.like(Department::getName, deptName);
		}
		List<Department> departments = this.getList(departmentLambdaQueryWrapper);
		if (CollectionUtils.isNotEmpty(departments)) {
			departments.forEach(department -> {
				OrgTreeVo orgTreeVo = new OrgTreeVo(department.getId(), department.getPid(), department.getName(),
						department.getName(), "2");
				orgTreeVo.setCode(department.getCode());
				orgTreeVos.add(orgTreeVo);
			});
		}
		return orgTreeVos;
	}

	@Override
	public List<OrgTreeVo> getOrgTree() {
		List<OrgTreeVo> orgTreeVos = companyService.getCompanyTree(null);
		Map<Integer, OrgTreeVo> companyMap = orgTreeVos.stream()
				.collect(Collectors.toMap(OrgTreeVo::getId, orgTreeVo -> orgTreeVo));
		List<Department> departments = mapper.getDepartments(new Department());
		if (CollectionUtils.isNotEmpty(departments)) {
			departments.forEach(department -> {
				OrgTreeVo orgTreeVo = new OrgTreeVo(department.getId(), department.getPid(), department.getName(),
						department.getName(), OrgTreeVo.DEPT_TYPE);
				if (department.getPid() == null) {
					orgTreeVo.setPid(department.getCompanyId());
				}
				orgTreeVo.setLeaderCode(department.getLeaderCode());
				orgTreeVo.setLeaderName(department.getLeaderName());
				Integer companyId = department.getCompanyId();
				OrgTreeVo company = companyMap.get(companyId);
				// 部门如果找不到公司，说明这个部门数据有问题。不加入组织树
				if (company != null) {
					orgTreeVo.setCompanyId(companyId);
					orgTreeVo.setCompanyName(company.getName());
					orgTreeVos.add(orgTreeVo);
				} else {
					log.error("{}【{}】部门找不到公司", orgTreeVo.getName(), orgTreeVo.getId());
				}
			});
		}
		return orgTreeVos;
	}

	@Override
	public Department getFinancialDept() {
		LambdaQueryWrapper<Department> departmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
		departmentLambdaQueryWrapper.eq(Department::getName, "财务科").eq(Department::getDelFlag, SysConstant.DEL_FLAG_1);
		return this.getOne(departmentLambdaQueryWrapper);
	}
}
